/*
 * Copyright  2017 NXP
 * All rights reserved.
 *
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <stdio.h>

#include "fsl_common.h"
#include "board.h"
#include "shmem.h"
#include "pq_tcn.h"
#include "tcn_param.h"
#include "rbuf32.h"

/*******************************************************************************
 * Definitions
 ******************************************************************************/

/*******************************************************************************
 * Prototypes
 ******************************************************************************/


/*******************************************************************************
 * Variables
 ******************************************************************************/
/* KWS系统中的内存分配. */
#define APP_KWS_CMD_FIFO_BUF_NUM    32u
uint32_t         app_kws_cmd_fifo_buf[APP_KWS_CMD_FIFO_BUF_NUM];
RBUF32_Handler_T app_kws_cmd_fifo_handle;

// for password app.
char          app_kws_word_str_buf[APP_KWS_CMD_FIFO_BUF_NUM];
uint32_t      app_kws_word_str_idx = 0;
bool          app_kws_word_on = false; /* kws is activated or not. */
const uint8_t app_kws_word_map[] =
{
    /* 0 */ '0',
    /* 1 */ '1',
    /* 2 */ '2',
    /* 3 */ '3',
    /* 4 */ '4',
    /* 5 */ '5',
    /* 6 */ '6',
    /* 7 */ '7',
    /* 8 */ '8',
    /* 9 */ '9',
    /* blank */ '#' /* start. */
};

uint32_t app_run_match(char * str, uint32_t val);

uint32_t app_match_value;

#define SHMEM_CMD_MSG_COUNT     4
shmem_cmd_msg_t app_shmem_cmd_msg[SHMEM_CMD_MSG_COUNT];
uint32_t  app_shmem_cmd_msg_idx = 0;

/*******************************************************************************
 * Code
 ******************************************************************************/
#if 0
void my_delay(uint32_t t)
{
    for (uint32_t i = 0u; i < t; i++)
    {
        for (uint32_t j = 0u; j < 100000; j++)
        {
            asm("nop");
        }
    }
}
#endif

uint32_t app_run_match(char * str, uint32_t val)
{
    uint32_t n;
    sscanf(str, "%d", &n);

    if (n == val)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}

/*!
 * @brief Main function.
 */
int main(void)
{
    board_init();
    printf("lpc5500 powerquad kws example.\r\n");

    /* core1 & lcd. */
    core1_init();
    shmem_wait_core_events(1u, SHMEM_CORE1_STAT_MAIN_START_MASK
                             | SHMEM_CORE1_STAT_HW_INIT_DONE_MASK
                             | SHMEM_CORE1_STAT_FIFO1_READY_MASK);
    printf("core1 ready.\r\n");

    /* kws cmd fifo. */
    RBUF32_Init(&app_kws_cmd_fifo_handle, app_kws_cmd_fifo_buf, APP_KWS_CMD_FIFO_BUF_NUM);
    srand(10); /* 初始化随机数发生器引擎. */
    app_kws_word_on = false; // disable the match at default.
    printf("variables ready.\r\n");

    /* powerquad. */
    pq_init_hardware();
    pq_tcn_init();
    printf("powerquad && tcn ready.\r\n");

    /* audio codec. */
    audio_codec_init();
    printf("audio codec ready .\r\n");

    while (1)
    {
        while (!RBUF32_IsEmpty(&app_kws_cmd_fifo_handle)) // ear is always on line.
        {
            char kws_cmd = app_kws_word_map[RBUF32_GetDataOut(&app_kws_cmd_fifo_handle)];

            //printf("kws_cmd: %c\r\n", kws_cmd);
            // 把常规识别放在前面, 也就是说默认情况下不识别.
            if (app_kws_word_on)
            {
                if (  (app_kws_word_str_idx >= 4) || (kws_cmd == '#')  )
                {
                     // 字符串输入超长或者收到结束符, 立即结束输入, 执行识别
                    app_kws_word_on = false;
                    app_kws_word_str_buf[app_kws_word_str_idx] = '\0';
                    uint32_t match_result = app_run_match(app_kws_word_str_buf, app_match_value);
                    if (0 == match_result)
                    {
                        printf("match suceced.\r\n");
                    }
                    else
                    {
                        printf("match failed.\r\n");
                    }
                    /* 给core1发送显示验证情况的命令 */
                    if (!app_shmem_cmd_msg[app_shmem_cmd_msg_idx].is_full)
                    {
                        app_shmem_cmd_msg[app_shmem_cmd_msg_idx].cmd  = shmem_fifo1_cmd_lcd_show_match;
                        app_shmem_cmd_msg[app_shmem_cmd_msg_idx].param[0] = match_result;
                        app_shmem_cmd_msg[app_shmem_cmd_msg_idx].is_full  = true;
                        shmem_fifo_push(1u, (uint32_t)&app_shmem_cmd_msg[app_shmem_cmd_msg_idx]);

                        /* 为下一次传递消息做好准备. */
                        app_shmem_cmd_msg_idx = (app_shmem_cmd_msg_idx+1)%SHMEM_CMD_MSG_COUNT;
                    }
                }
                else
                {
                    app_kws_word_str_buf[app_kws_word_str_idx] = kws_cmd;
                    printf("%c\r\n", kws_cmd);

                    /* 给core1发送当前输入验证码数字的命令 */
                    if (!app_shmem_cmd_msg[app_shmem_cmd_msg_idx].is_full)
                    {
                        app_shmem_cmd_msg[app_shmem_cmd_msg_idx].cmd  = shmem_fifo1_cmd_lcd_show_passcode;
                        app_shmem_cmd_msg[app_shmem_cmd_msg_idx].param[0] = app_kws_word_str_idx;
                        app_shmem_cmd_msg[app_shmem_cmd_msg_idx].param[1] = kws_cmd - '0'; /* char to number. */
                        app_shmem_cmd_msg[app_shmem_cmd_msg_idx].is_full  = true;
                        shmem_fifo_push(1u, (uint32_t)&app_shmem_cmd_msg[app_shmem_cmd_msg_idx]);

                        /* 为下一次传递消息做好准备. */
                        app_shmem_cmd_msg_idx = (app_shmem_cmd_msg_idx+1)%SHMEM_CMD_MSG_COUNT;
                    }

                    app_kws_word_str_idx++;
                }
            }
            else // 在关闭匹配的情况下, 只有'#'才能激活匹配过程.
            {
                if (kws_cmd == '#')
                {
                    app_kws_word_on = true; // activate the match process

                    // init the match process.
                    RBUF32_Reset(&app_kws_cmd_fifo_handle); // reset fifo
                    app_kws_word_str_idx = 0; // reset buffer.

                    app_match_value = rand() % 10000;
                    printf("new password: %d\r\n", app_match_value);

                    /* 给core1发送刷新屏幕并显示验证码的命令 */
                    if (!app_shmem_cmd_msg[app_shmem_cmd_msg_idx].is_full)
                    {
                        app_shmem_cmd_msg[app_shmem_cmd_msg_idx].cmd  = shmem_fifo1_cmd_lcd_new_passcode;
                        app_shmem_cmd_msg[app_shmem_cmd_msg_idx].param[0] = (app_match_value / 1000);
                        app_shmem_cmd_msg[app_shmem_cmd_msg_idx].param[1] = (app_match_value / 100) % 10;
                        app_shmem_cmd_msg[app_shmem_cmd_msg_idx].param[2] = (app_match_value / 10) % 10;
                        app_shmem_cmd_msg[app_shmem_cmd_msg_idx].param[3] = (app_match_value % 10);
                        app_shmem_cmd_msg[app_shmem_cmd_msg_idx].is_full  = true;
                        shmem_fifo_push(1u, (uint32_t)&app_shmem_cmd_msg[app_shmem_cmd_msg_idx]);

                        /* 为下一次传递消息做好准备. */
                        app_shmem_cmd_msg_idx = (app_shmem_cmd_msg_idx+1)%SHMEM_CMD_MSG_COUNT;
                    }


                }
            } /* end if. */
        } /* end while. */
    }
}

uint32_t g_kws_value;
void audio_codec_rx_frame_hook(uint16_t *buff, uint32_t len)
{
    // 开始计时
    //TimerCount_Start();

    /* 处理音频数据, 进行识别 */
    pq_tcn_preprocess(buff); /* FFT变换 */
    g_kws_value = pq_tcn_run(); /* TCN推理 */

    // 结束计时
    //TimerCount_Stop(g_kws_nn_time);
    //g_shmem_words[SHMEM_GUI_NN_TIME_REG_IDX] = g_kws_nn_time;

    if (g_kws_value < 11)
    {
        if (!RBUF32_IsFull(&app_kws_cmd_fifo_handle))
        {
            RBUF32_PutDataIn(&app_kws_cmd_fifo_handle, g_kws_value); /* 识别结果入队. */
        }
    }
}

/* EOF. */

